package it.yuzuojian.com.aop;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;
import java.util.Map;


public class AopFactory {
    private static List<GPAopConfig> configs;

    public static Object getProxy(GPAdviceSupport config, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Map<String, List<GPAdvice>> adviceMap=config.getAdvices(method,config.getTargetClass());
        Object result=null;
        try {

            List<GPAdvice> befores = adviceMap.get("before");
            befores.sort(new Comparator<GPAdvice>() {
                @Override
                public int compare(GPAdvice o1, GPAdvice o2) {
                    return o1.getOrder()- o2.getOrder();
                }
            });
            for (GPAdvice before : befores) {
                before.getAdviceMethod().invoke(before.getAspect());
            }
            result=method.invoke(config.getTarget(),args);
            List<GPAdvice> afters = adviceMap.get("after");
            afters.sort(new Comparator<GPAdvice>() {
                @Override
                public int compare(GPAdvice o1, GPAdvice o2) {
                    return o2.getOrder()- o1.getOrder();
                }
            });
            for (GPAdvice after : afters) {
                after.getAdviceMethod().invoke(after.getAspect());
            }
        } catch (Exception e) {
            e.printStackTrace();
            List<GPAdvice> afterThrowings = adviceMap.get("afterThrowing");
            afterThrowings.sort(new Comparator<GPAdvice>() {
                @Override
                public int compare(GPAdvice o1, GPAdvice o2) {
                    return o2.getOrder()- o1.getOrder();
                }
            });
            for (GPAdvice afterThrowing : afterThrowings) {
                afterThrowing.getAdviceMethod().invoke(afterThrowing.getAspect());
            }
        }
        return result;
    }


    public static List<GPAopConfig> getConfigs() {
        return configs;
    }

    public static void setConfigs(List<GPAopConfig> configs) {
        AopFactory.configs = configs;
    }
}
